﻿using System;
using RockCorn.Internals;
using RockCorn.Objects;
using RockCorn.Objects.Moving;
using RockCorn.Interfaces;

namespace RockCorn
{
    class RockCornMain
    {
        const int WorldRows = 25; // >=5
        const int WorldCols = 40; // >=15
        const int RacketLength = 11;
        static int level = 0;

        private static void InitializeLevel(Engine engine, int level, int startRow, int startCol, int WorldRows, int WorldCols, int levelRacketLength)
        {
            int endCol = WorldCols - 2;
            Random rand = new Random();
            int posYSpecial = 0;
            int posXSpecial = 0;

            for (int row = 0; row < level + 1; row++) // how many rows with blocks
            {
                posYSpecial = rand.Next(startCol, WorldCols - 2);
                int posYSpecial2 = rand.Next(startCol, WorldCols - 2);
                int posYSpecial3 = rand.Next(startCol, WorldCols - 2);

                for (int i = startCol; i < endCol; i++)
                {
                    if (i == posYSpecial2 || i == posYSpecial)
                    {
                        ExplodingBlock boom = new ExplodingBlock(new MatrixCoords(startRow + row, i));
                        engine.AddObject(boom);
                    }
                    else if (i == posYSpecial3)
                    {
                        GiftBlock gift = new GiftBlock(new MatrixCoords(startRow + row, i));
                        engine.AddObject(gift);
                    }
                    else
                    {
                        Block currBlock = new Block(new MatrixCoords(startRow + row, i));
                        engine.AddObject(currBlock);
                    }
                }
            }

            // generate random position for gifts 
            posYSpecial = 0;
            posXSpecial = 0;
            int numberOfRandomGiftBlocks = level < 3 ? level * 5 : level + 10;

            for (int i = 1; i < numberOfRandomGiftBlocks; i++)
            {
                posXSpecial = rand.Next(startRow, ((level + 3) > WorldRows - 3) ? WorldRows - 3 : level + 3);
                posYSpecial = rand.Next(startCol, WorldCols - 2);

                GiftBlock gift = new GiftBlock(new MatrixCoords(posXSpecial, posYSpecial));
                engine.AddObject(gift);
            }


            // Top unpassable blocks (ceiling)
            for (int i = 0; i < WorldCols; i++)
            {
                UnpassableBlock currBlock = new UnpassableBlock(new MatrixCoords(0, i));
                engine.AddObject(currBlock);
            }

            // Left and right walls of unpassable blocks
            for (int i = 0; i < WorldRows; i++)
            {
                UnpassableBlock currBlock = new UnpassableBlock(new MatrixCoords(i, 0));
                UnpassableBlock currBlock2 = new UnpassableBlock(new MatrixCoords(i, WorldCols - 1));

                engine.AddObject(currBlock);
                engine.AddObject(currBlock2);
            }

            // align center 
            ShootingRacket theRacket = new ShootingRacket(new MatrixCoords(WorldRows - 1, (WorldCols - levelRacketLength) / 2), levelRacketLength); 
            engine.AddObject(theRacket);


            MeteoriteBall theBall = new MeteoriteBall(new MatrixCoords(theRacket.GetTopLeft().Row - 1, theRacket.GetTopLeft().Col + (levelRacketLength / 2)), new MatrixCoords(-1, 1));
            engine.AddObject(theBall);
        }

        static void Main(string[] args)
        {
            int score = 0;

            WelcomeScreen welcome = new WelcomeScreen(WorldRows, WorldCols);
            IRenderer renderer = new ConsoleRenderer(WorldRows, WorldCols);
            IUserInterface keyboard = new KeyboardInterface();
            welcome.PrintMessage();

            do
            {
                ShootableRacketEngine gameEngine = new ShootableRacketEngine(renderer, keyboard, 150, score);

                keyboard.OnLeftPressed += (sender, eventInfo) =>
                {
                    gameEngine.MovePlayerRacketLeft();
                };

                keyboard.OnRightPressed += (sender, eventInfo) =>
                {
                    gameEngine.MovePlayerRacketRight();
                };

                keyboard.OnActionPressed += (sender, eventInfo) =>
                {
                    gameEngine.ShootPlayerRacket();
                };

                int startRow = 2;
                int startCol = 2;

                level++;
                if (level > WorldRows - 10) level = WorldRows - 10;

                int levelRacketLength = RacketLength - 2 * level;
                if (levelRacketLength < 3) levelRacketLength = 3;

                InitializeLevel(gameEngine, level, startRow, startCol, WorldRows, WorldCols, levelRacketLength);

                gameEngine.Run();

                score = gameEngine.Score;

            } while (true);
        }
    }
}